/**
 * https://www.bilibili.com/video/BV1vs411n7TH/?p=113
 * https://www.bilibili.com/video/BV1vs411n7TH?p=114
 *
 * 文件: 文本文件 & 二进制文件 & 设备文件
 * 1.文本文件:
 *   基于字符编码, 常见编码有ASCII, UNICODE 等,
 *   一般可以用文本编辑器直接打开.
 *   例: 数5678的以ASCII存储形式(ASCII码)为:
 *       00110101 00110110 00110111 00111000
 *
 * 2.二进制文件:
 *   基于值编码, 自己根据具体应用, 指定某个值是什么意思.
 *   把内存中的数据按其在内存中的存储形式原样输出到磁盘上.
 *   例: 数5678的存储形式(二进制码)为:
 *       00010110 00101110
 *
 * 3.设备文件(嵌入式)
 *   TODO
 */
#include <stdio.h>
#include <stdlib.h>
#include "../Utils/FileIOUtils.h"

//绝对路径
//static char *FILE_READ_PATH = "F:\\workspace_cpp\\CLion\\Clion_CppTest\\Read_Write_Test\\test.txt";
//使用相对位置
static char *FILE_READ_PATH = "../Read_Write_Test/test.txt";
static char *FILE_WRITE_PATH = "../Read_Write_Test/1.写测试.txt";
static char *FILE_WRITE_S_PATH = "../Read_Write_Test/1.写字符串测试.txt";
static char *str = "Hello World!你好世界!\n";

void open_file();
void read_char();
void write_char();
void read_str();
void write_str();
void close_file();

FILE *readFile, *writeFile;
int main() {
    //1.打开文件
//    open_file();
//    //2.读文件
//    read_char();
//    //3.写文件
//    write_char();
//    close_file();   //读写另外的文件前, 先关闭文件

    //4.读取字符串
//    read_str();
    //5.写入字符串
    write_str();

    // .关闭文件
    close_file();
    return EXIT_SUCCESS;
}

//1.打开&关闭文件
void open_file() {
    readFile = file_open_r(FILE_READ_PATH);
    if (readFile == NULL) printf("打开文件失败!");
    else printFile(readFile, 1, 1);
}

//2.读文件
void read_char() {
    printf("2.读取字符\n");
    int c;
    while (!file_eof(readFile)) {
        c = file_getc(readFile);
        printf("%c", c);
    }
}

//3.写文件
void write_char() {
    writeFile = file_open_w(FILE_WRITE_PATH);
    if (writeFile == NULL) printf("打开文件失败!");
    else {
        char *temp = str;                   //temp: 防止str指针改变
        while (*temp) {
            int c = file_putc(*temp++, writeFile);
        }
        printf("3.写文件完成: %s\n", FILE_WRITE_PATH);
    }
}

//4.读取字符串
void read_str() {
    printf("4.读取字符串\n");
    readFile = file_open_r(FILE_READ_PATH);
//    char arr[999];                        //写成字符数组也可以
    char *arr = malloc(sizeof(char) * 999);

    //1.读取字符串
    char *str0 = file_gets(arr, 999, readFile);
    printf("1.读取字符串: %s", arr);
    
    //2.光标前移10位
    int fail0 = file_seek(readFile, -10, SEEK_CUR);
    char *str1 = file_gets(arr, 999, readFile);
    printf("2.光标从SEEK_CUR(当前位置)偏移 %d 位, 再读取字符串: %s", -10, arr);

    //3.继续往下读
//    while (!file_eof(readFile)) {         //这样判断也可以.
    while (file_gets(arr, 999, readFile)) { //file_gets返回值和arr一样, 读取完了=NULL
        printf("%s", arr);
//        memset(arr, 0, 999);              //读取1行会自动'\0'结尾, 不用初始设置
    }

    free(arr);
}

//5.写入字符串
void write_str() {
    writeFile = file_open_w(FILE_WRITE_S_PATH);
    int fail0 = file_puts(str, writeFile);
    int fail1 = file_puts(str, writeFile);       //写入第2行

    int fail2 = file_seek(writeFile, -20, SEEK_CUR);
    int fail3 = file_puts("3.插入!\n", writeFile);//插入
    printf("1.光标从SEEK_CUR(当前位置)偏移 %d 位, 并写入了第3句字符串.\n", -20);
    printf("5.写入字符串完成: %s\n", FILE_WRITE_S_PATH);
}

// .关闭文件
void close_file() {
    file_close(readFile);
    file_close(writeFile);
}
